#pragma once
#ifndef PSRAM_MANAGER_H
#define PSRAM_MANAGER_H

#include <esp_heap_caps.h>
#include <esp32/rom/cache.h>
#include "log.h"

// WAV文件头结构体
struct MemoryBlock
{
    void *ptr;
    size_t blockSize;
    uint8_t mode; // SRAM or PSRAM
    MemoryBlock* next;
};

class Memory
{
private:
    MemoryBlock *head;

    // 当前已使用内存大小 (字节)
    size_t usedSramMemory = 0;
    size_t usedPsramMemory = 0;

    // maximum memory size (字节)
    size_t maxSramMemory = 0;
    size_t maxFlashMemory = 0;
    size_t maxPsramMemory = 0;

    bool isPsramFound = false;

public:
    Memory();

    void init();

    // 获取当前已使用内存大小
    size_t getUsedSramMemory();
    size_t getUsedPsramMemory();

    // 获取最大内存大小
    size_t getMaxSramMemory();
    size_t getMaxPsramMemory();

    // 内存申请
    void *allocate(size_t size, uint8_t mode);

    // 内存释放
    void deallocate(void *ptr);

    MemoryBlock *getHead();

    void clear();

    ~Memory();
};

enum ALLOCATE_MODE
{
    SRAM = 0, // 320KB on ESP32 N2R4
    PSRAM     // 2048KB on ESP32 N2R4
};

extern Memory memory;

void initMemory();

void *pMalloc(size_t n);

void Free(void *ptr);

size_t getMaxSramMemory();
size_t getMaxPsramMemory();

size_t getUsedSramMemory();
size_t getUsedPsramMemory();

size_t getFreeSramMemory();
size_t getFreePsramMemory();

void ClearMemory();

void getHeadAdress(int a); // 获取头指针地址

void printMemoryInfo(char *msg);

#define Malloc(type, n) (type *)pMalloc((n) * sizeof(type));

#endif // PSRAM_MANAGER_H